<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        canvas {
          width: 100%;
          height: 100%;
        }
      </style>
</head>
<body>
    
    <canvas id="canvas"></canvas>

    <script>
      const canvas = document.getElementById('canvas');
      const ctx = canvas.getContext('2d');
    
      // 定义立方体的顶点坐标和面的顶点索引
      const vertices = [
        [-1, -1, -1],
        [-1, -1, 1],
        [-1, 1, -1],
        [-1, 1, 1],
        [1, -1, -1],
        [1, -1, 1],
        [1, 1, -1],
        [1, 1, 1],
      ];
    
      const faces = [
        [0, 1, 3, 2],
        [4, 5, 7, 6],
        [0, 1, 5, 4],
        [2, 3, 7, 6],
        [0, 2, 6, 4],
        [1, 3, 7, 5],
      ];
    
      // 定义相机位置和朝向
      let cameraX = 0;
      let cameraY = 0;
      let cameraZ = -5;
      let targetX = 0;
      let targetY = 0;
      let targetZ = 0;
    
      // 定义投影矩阵和透视矩阵
      const projectionMatrix = [
        [canvas.height / canvas.width, 0, 0, 0],
        [0, 1, 0, 0],
        [0, 0, -1, -1],
        [0, 0, 0, 1],
      ];
    
      const perspectiveMatrix = [
        [1, 0, 0, 0],
        [0, 1, 0, 0],
        [0, 0, 1, 0],
        [0, 0, 1 / cameraZ, 0],
      ];
    
      // 定义角度变量，用于旋转
      let theta = 0;
    
      // 定义draw函数，用于绘制立方体
      function draw() {
        // 清空画布
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    
        // 计算旋转矩阵
        const rotationMatrix = [
          [Math.cos(theta), 0, Math.sin(theta), 0],
          [0, 1, 0, 0],
          [-Math.sin(theta), 0, Math.cos(theta), 0],
          [0, 0, 0, 1],
        ];
    
        // 计算相机和目标的位置
        const camera = [cameraX, cameraY, cameraZ];
        const target = [targetX, targetY, targetZ];
    
        // 计算坐标变换矩阵
        const transformMatrix = matrixMultiply(
          projectionMatrix,
          perspectiveMatrix,
          rotationMatrix,
          translationMatrix(target[0], target[1], target[2]),
          inverseTranslationMatrix(camera[0], camera[1], camera[2])
        );
        // 遍历每个面，并绘制到Canvas上
for (let i = 0; i < faces.length; i++) {
  const face = faces[i];
  const points = [];

  // 遍历面上的每个顶点，将其进行坐标变换，然后转换为Canvas坐标系上的坐标
  for (let j = 0; j < face.length; j++) {
    const vertex = vertices[face[j]];
    const transformedVertex = transformVertex(vertex, transformMatrix);
    const canvasVertex = projectVertex(transformedVertex, canvas.width, canvas.height);
    points.push(canvasVertex);
  }

  // 绘制面
  ctx.beginPath();
  ctx.moveTo(points[0].x, points[0].y);
  for (let j = 1; j < points.length; j++) {
    ctx.lineTo(points[j].x, points[j].y);
  }
  ctx.closePath();
  ctx.stroke();
}
// 更新角度
theta += 0.01;

// 重复执行
requestAnimationFrame(draw);
      }
      // 定义矩阵相乘函数
function matrixMultiply() {
let matrix = arguments[0];
for (let i = 1; i < arguments.length; i++) {
matrix = multiply(matrix, arguments[i]);
}
return matrix;
}

function multiply(a, b) {
const result = [];
for (let i = 0; i < 4; i++) {
result[i] = [];
for (let j = 0; j < 4; j++) {
let sum = 0;
for (let k = 0; k < 4; k++) {
sum += a[i][k] * b[k][j];
}
result[i][j] = sum;
}
}
return result;
}

// 定义顶点坐标变换函数
function transformVertex(vertex, transformMatrix) {
const [x, y, z] = vertex.concat(1);
const [tx, ty, tz, tw] = multiply(transformMatrix, [x, y, z, 1]);
return [tx / tw, ty / tw, tz / tw];
}

// 定义坐标投影函数
function projectVertex(vertex, width, height) {
const [x, y, z] = vertex;
const projectedX = (x + 1) * width / 2;
const projectedY = (1 - y) * height / 2;
return { x: projectedX, y: projectedY };
}

// 定义平移矩阵和逆平移矩阵
function translationMatrix(tx, ty, tz) {
return [
[1, 0, 0, tx],
[0, 1, 0, ty],
[0, 0, 1, tz],
[0, 0, 0, 1],
];
}

function inverseTranslationMatrix(tx, ty, tz) {
return [
[1, 0, 0, -tx],
[0, 1, 0, -ty],
[0, 0, 1, -tz],
[0, 0, 0, 1],
];
}

// 开始绘制
draw();
 </script>
    

</body>
</html>